package pl.edu.agh.jemo.evolution.genotype.impl;

import pl.edu.agh.jemo.evolution.common.JemoRandom;
import pl.edu.agh.jemo.evolution.genotype.Genotype;

/**
 * Wrapper for single dimension genotype value stored as Double.
 * 
 * @author Marcin Zbijowski
 */
public class DoubleGenotype implements Genotype {

	/**
	 * Parameter holding stored value of specimen genotype.
	 */
	protected Double value = 0.;
	
	/**
	 * Constructor creating new genotype with specified value.
	 *
	 * @param value Initial value of newly created genotype.
	 */
	public DoubleGenotype(Double value) {
		this();
		fromDouble(value);
	}


	public DoubleGenotype() {
	}

	/**
	 * Creates new instance of DoubleGenotype class.
	 * The value of new object will be the same as value of object on which method is called.
	 * 
	 * @return New instance of DoubleGenotype class.
	 */
	@Override
	public DoubleGenotype clone() {
		DoubleGenotype result = new DoubleGenotype(value);
		return result;
	}
	
		/**
	 * Compares stored value to another genotype value.
	 * Comparison is made between values casted to Double, so diffrent Genotype implementations might be compared
	 * 
	 *  @param anotherValue Another object of Genotype implementation, to which object is compared
	 *  @return 0 if both Genotypes hold equal values, 1 if stored value is grater than anotherValue, -1 if stored value is lesser than anotherValue
	 */
	@Override
	public int compareTo(Genotype anotherValue) {
		return value.compareTo(anotherValue.asDouble());
	}
	
	/**
	 * Returns stored value.
	 * 
	 * @return Value of stored genotype.
	 */
	@Override
	public Double asDouble() {
		return value;
	}
	
	

	/**
	 * Sets value of genotype.
	 *
	 * @param value New value of genotype, to be stored by this object.
	 */
	@Override
	public void fromDouble(Double value) {
		this.value = value;		
	}
	
	/**
	 * Generates random specimen genotype value based on given boundaries.
	 * 
	 * @param lower Lowest possible value of new genotype (inclusive)
	 * @param upper	Highest possible value of new genotype (exclusive)
	 */
	@Override
	public void generateValue(Double lower, Double upper) {
		value = JemoRandom.getRandom().nextDouble()* (upper - lower) + lower;
	}

	/**
	 * Generates random specimen genotype value based on given boundaries.
	 * 
	 * @param boundaries Array of two elements, were first is treated as lower and second as higher boundary
	 * @see #generateValue(Double, Double)
	 */
	@Override
	public void generateValue(Double[] boundaries) {
		generateValue(boundaries[0], boundaries[1]);
	}
	
	/**
	 * Returns text description of stored value
	 * 
	 * @return String with stored value formated to display 4 digits after comma
	 */
	@Override
	public String toString() {
		return String.format("%.4f", value);
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((value == null) ? 0 : value.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		DoubleGenotype other = (DoubleGenotype) obj;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		return true;
	}	
}
